package name.fowler.refactoring.simplestore.web;

import name.fowler.refactoring.simplestore.domain.*;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
import java.util.List;
import java.util.Map;

public class ContentHandler implements Serializable {
    public ContentHandler() {
    }

    void addEntity(String[] pathItem, Map<String, String[]> params, EntityManager entityManager) {
        JPAEntity entity = createEntity(params, pathItem[0], entityManager);
        entityManager.getTransaction().begin();
        if (entity.getId() == 0) {
            entityManager.persist(entity);
        } else {
            entityManager.merge(entity);
        }
        entityManager.getTransaction().commit();
    }

    void deleteEntity(String[] pathItem, Map<String, String[]> params, EntityManager entityManager) {
        int id = Integer.valueOf(params.get("id")[0]);
        if (pathItem[0].equals("rental")) {
            Integer customerId = Integer.valueOf(params.get("customer_id")[0]);
            Customer customer = entityManager.find(Customer.class, customerId);
            Rental rental = entityManager.find(Rental.class, id);
            customer.getRentals().remove(rental);
            entityManager.getTransaction().begin();
            entityManager.merge(customer);
            entityManager.getTransaction().commit();
        } else {
            entityManager.getTransaction().begin();
            JPAEntity entity = entityManager.find(getClazz(pathItem[0]), id);
            entityManager.remove(entity);
            entityManager.getTransaction().commit();
        }
    }

    JPAEntity createEntity(Map<String, String[]> params, String s, EntityManager entityManager) {
        switch (s) {
            case "movie": {
                String movieName = params.get("movieName")[0];
                PriceCodes priceCode = PriceCodes.valueOf(params.get("priceCode")[0]);
                return new Movie(movieName, priceCode);
            }
            case "customer": {
                String name = params.get("name")[0];
                String nickName = params.get("nickName")[0];
                Customer customer = new Customer(name);
                customer.setNickName(nickName);
                return customer;
            }
            case "rental": {
                Integer customerId = Integer.valueOf(params.get("customer_id")[0]);
                Integer movieId = Integer.valueOf(params.get("movieId")[0]);
                Integer daysRented = Integer.valueOf(params.get("daysRented")[0]);
                Customer customer = entityManager.find(Customer.class, customerId);
                Movie movie = entityManager.find(Movie.class, movieId);
                customer.addRental(movie, daysRented);
                return customer;
            }
            default:
                return null;
        }
    }

    void showContent(EntityManager entityManager, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
        String pathInfo = httpServletRequest.getPathInfo();
        String[] pathItem = pathInfo.substring(1).split("/");
        httpServletRequest.setAttribute("title", pathItem[0] + " " + pathItem[pathItem.length - 1]);
        addDateToRequest(entityManager, httpServletRequest, pathItem[0], pathItem[1]);
        httpServletRequest.getServletContext().getRequestDispatcher("/WEB-INF" + pathInfo + ".jsp")
                .forward(httpServletRequest, httpServletResponse);
    }

    void addDateToRequest(EntityManager entityManager, HttpServletRequest httpServletRequest, String dataType, String action) {
        if (action.equals("list")) {
            List<? extends JPAEntity> entityList;
            if (dataType.equals("rental")) {
                Integer customer_id = Integer.valueOf(httpServletRequest.getParameter("customer_id"));
                Customer customer = entityManager.find(Customer.class, customer_id);
                entityList = customer.getRentals();
            } else {
                TypedQuery<? extends JPAEntity> query = entityManager.createNamedQuery(dataType + '.' + action,
                        getClazz(dataType));
                entityList = query.getResultList();
            }
            httpServletRequest.setAttribute("entityList", entityList);
        } else if (action.equals("add")) {
            if (dataType.equals("rental")) {
                List<Movie> movieList = entityManager.createNamedQuery("movie.list", Movie.class).getResultList();
                httpServletRequest.setAttribute("movieList", movieList);
            }
        }
    }

    Class<? extends JPAEntity> getClazz(String s) {
        switch (s) {
            case "movie":
                return Movie.class;
            case "customer":
                return Customer.class;
            case "rental":
                return Rental.class;
            default:
                return null;
        }
    }
}